﻿using FireChat.Client.Session.Receiver;
using FireChat.Share.Logger;
using FireChat.Share.Web.Actions;
using FireChat.Share.Web.Package;
using FireChat.Share.Web.Util;
using System.Net.WebSockets;

namespace FireChat.Client.Session;


/// <summary>
/// Fire Chat 客户端核心
/// </summary>
public class ClientCore
{
    /// <summary>
    /// 客户端 websocket
    /// </summary>
    private readonly ClientWebSocket _clientWebSocket = new();

    /// <summary>
    /// 接收到的服务器响应缓存
    /// </summary>
    private readonly PackageBuffer<ServerPackage> _receivedResponseBuffer = new();



    /// <summary>
    /// 服务器地址
    /// </summary>
    public Uri ServerUri { get; }

    /// <summary>
    /// 接收到数据包事件
    /// </summary>
    public event Action<PackageReceiver>? PackageReceiver;



    /// <summary>
    /// 初始化客户端
    /// </summary>
    /// <param name="serverUri">服务器地址</param>
    public ClientCore(string serverUri)
    {
        ServerUri = new(serverUri);

        PackageReceiver += receiver =>
        {
            if (receiver.Package.ActionType != ClientActions.Response)
            {
                return;
            }

            _receivedResponseBuffer.Add(receiver.Package);
        };
    }



    /// <summary>
    /// 启动客户端
    /// </summary>
    /// <returns></returns>
    public async Task LaunchAsync()
    {
        await _clientWebSocket.ConnectAsync(ServerUri, CancellationToken.None);

        $"FireChat 客户端核心 已连接服务器 [{ServerUri}]".LogToConsole();

        await _clientWebSocket.ReceivePackageAsync<ServerPackage>(
        package =>
        {
            PackageReceiver?.Invoke(new() { Session = this, Package = package });
        },
        ex =>
        {
            if(ex is WebSocketException websocket_ex)
            {
                $"与服务器断开连接: {websocket_ex.Message}".LogToConsole();
                return false;
            }
            ex.LogToConsole();

            return true;
        });
    }

    /// <summary>
    /// 关闭客户端核心
    /// </summary>
    /// <returns></returns>
    public Task CloseAsync()
    {
        return _clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None);
    }



    /// <summary>
    /// 发送数据包
    /// </summary>
    internal Task SendAsync(ClientPackage package)
    {
        return _clientWebSocket.SendAsync(package);
    }

    /// <summary>
    /// 发送并获取回应
    /// </summary>
    internal async Task<ServerPackage> SendReceiveAsync(ClientPackage package)
    {
        await _clientWebSocket.SendAsync(package);

        return await _receivedResponseBuffer.GetAsync(x => x.Id == package.Id) ?? ServerPackage.Empty;
    }
}